接著,就是刪除文章了對吧!應該跟前面的新增修改沒有什麼兩樣吧。
這時候!我們突然接到了一個需求:
「是這樣,因為很多用戶常常會希望能復原之前不小心刪掉的內容,所以不知道可不可以,文章看起來刪掉了,但是實際上沒有刪掉呢?」
可以的!這時候我們就要來介紹 Laravel 物件另一個特別的功能:軟刪除(Soft Delete)!
前面的需求來說,我們可以想到,勢必在使用者刪除掉我們的資料時,我們資料庫內的資料,不會真的刪除,而是加上某個標籤,標記我們「刪除」了這筆資料。
這個判斷的邏輯,在 Laravel 裡面,也已經打包好囉!我們就直接來實作看看
我們先幫 Post 增加一個 migration 看看
$ php artisan make:migration add_soft_delete_to_posts_table
Created Migration: 2019_09_22_142336_add_soft_delete_to_posts_table
然後,我們改寫一下這個 migration
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddSoftDeleteToPostsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}
我們利用 Laravel 提供的函式,幫助我們快速建立軟刪除相關的欄位。
接著,我們跑一下 migration
$ php artisan migrate
Migrating: 2019_09_22_142336_add_soft_delete_to_posts_table
Migrated: 2019_09_22_142336_add_soft_delete_to_posts_table (0.8 seconds)
成功的話,回去看看資料庫的 posts
資料表,應該可以看到多了一個 deleted_at
欄位,這樣我們資料表就準備完成囉!
不過,我們還是要養成記得處理 migration down()
的好習慣,以免之後 rollback 失敗造成困擾。
我們改寫剛剛 migration 的 down()
函式
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('posts', function (Blueprint $table) {
$table->dropSoftDeletes();
});
}
加上了 dropSoftDeletes()
,我們測試看看
php artisan migrate:rollback --step=1
Rolling back: 2019_09_22_142336_add_soft_delete_to_posts_table
Rolled back: 2019_09_22_142336_add_soft_delete_to_posts_table (0.64 seconds)
跑完之後,如果可以看到 deleted_at
從資料表中消失,那就代表我們成功囉!
接著我們再執行一次 php artisan migrate
,確認資料表格式是我們需要的樣子後,開始在物件裡加上軟刪除
我們在 Post
物件最前面,加上 use SoftDeletes;
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model
{
use SoftDeletes;
好了,完成了。
簡單的很不可思議吧!我們嘗試用測試路徑刪掉一筆資料看看
Route::get('/test', function(){
$post = Post::find(1);
$post->delete();
});
然後點擊 http://127.0.0.1/test 之後,看看資料庫的資料
成功的話,應該可以看到 id
為 1 的資料,deleted_at
不再是 NULL
了,而是一個時間戳記!
這時候我們嘗試存取 id
為 1 的 Post
Route::get('/test', function(){
$post = Post::find(1);
return $post;
});
點擊 http://127.0.0.1/test 之後,什麼都看不到!我們成功了!
軟刪除的設置做完之後,我們就可以來建立刪除的路徑了。
我們在編輯文章的頁面裡面,加上一個刪除文章的按鈕
改寫 resources/views/edit.blade.php
如下
編輯文章
<form action="{{ route('posts.update', [ 'post' => $post]) }}" method="POST">
@method('PUT')
@csrf
<label>內容:
<textarea name="content">{{ $post->content }}</textarea>
</label><br>
<input type="submit" value="送出文章">
</form>
<form action="{{ route('posts.destroy', [ 'post' => $post]) }}" method="POST">
@method('DELETE')
@csrf
<input type="submit" value="刪除文章">
</form>
這樣,在編輯文章的畫面下,我們就多了一個刪除文章的表單,裡面只包含一個按鈕:「刪除文章」。
接著我們改寫 PostController
的 destroy()
public function destroy(Post $post)
{
$post->delete();
return redirect(route('posts.index'));
}
好了!我們隨便選一篇文章的編輯頁面(比方說 http://127.0.0.1/posts/3/edit ),然後點下「刪除文章」的按鈕。
點完之後,我們到資料庫看看該文章的資料,順利的話應該可以看到 id
為 3 的文章,deleted_at
欄位已經加上時間戳記,代表我們文章已經刪除囉!這時我們再次嘗試進入 http://127.0.0.1/posts/3/edit 時,應該會看見 「404 Not Found」 的字樣
想要把文章復原,只要我們在資料庫裡面,把對應資料的 deleted_at
改成 NULL
,文章就會正常顯示,也可以正常的編輯囉!
到這邊,我們對文章的所有動作,正式告一段落了!
小小總結一下今天我們學到些什麼。
今天我們學到什麼是軟刪除,怎麼利用 Laravel 快速的建立軟刪除的資料,還學到怎麼建立刪除的功能。
希望各位讀者覺得今天的文章有學到東西,我們明天見!
SoftDeletes
Trait 需引入 namespace:
use Illuminate\Database\Eloquent\SoftDeletes;
class Post extends Model
{
use SoftDeletes;
對!我忽略這一段了,感謝!
請問老師,
假設某筆文章被改了三次,
laravle 有沒有類似 Soft Delete 這樣的機制,
可以追蹤這三次修改的內容,而且可以回溯到任何一次的原始內容?
就我所知沒有,目前我只想到自己手動做追蹤紀錄的方式